package study.JavaBase;
import com.animal.Person_test;
import toTest.ReflectTest;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * date:2025.10.16
 * title:反射
 * author:fzy
 */

//反射QAQ，最被崩溃的一集6666666666666666666666666666666666666666666666666666666666666666666666
//强大特性，允许程序在运行时查询，访问，修改类，接口，字段，方法信息，可以动态操作类 q:什么叫运行时？
//反射API
//java.lang.Class :表示类对象，提供方法获取类的字段，方法，构造函数
//---------.reflect.Field:表示类的字段，提供了访问和修改字段的能力
//-----------------.Method:表示类的方法，提供了调用方法的能力
//-----------------.Constructor:表示类构造函数，提供创建对象的能力
/*

工作流程
1、获取class对象（实例化？不太明白）
2、获取成员信息（这下看懂了，获取class对象，class是lang包的对象，要用这个对象的能力）
3、操作成员，通过反射API读取修改字段的值，调用方法和创建对象（又不懂了，）
 */
public class Java_25 {

    static void reflectStepOne() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //通过类字面量
        //Class<?> clazz = String.class;
        //通过对象实例
        //String a = "Str";
        //Class<?> clazz = a.getClass();
        //通过class.forname
        Class clazz = Class.forName("java.lang.String");

    }
    static void reflectStepTwo() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class clazz = Class.forName("java.lang.String");
        clazz.getDeclaredConstructor().newInstance();
    }

    static void reflectStepThree() throws InstantiationException, IllegalAccessException, NoSuchFieldException {
        //这里是创建了一个Person_test类的Class对象，用于后续获取实例
        Class clazz_1 = Person_test.class;
        //这里利用class对象获取了person_test的实例
        Person_test person = (Person_test)clazz_1.newInstance();
        //通过class对象的getDeclaredField方法获取字段的Field对象
        Field field = clazz_1.getDeclaredField("name");
        //设置可修改
        field.setAccessible(true);
        //获取这个字段值的数值
        Object value  = field.get(person);
        System.out.println(value);
        //修改这个字段值的数值
        field.set(person,"fuzhiyu");
        Object value2 = field.get(person);
        System.out.println(value2);
        //总结总结：获取field对象需要用到class对象，class对象主要是获取实例，field类用来对这个实例某一个变量，方法获取对象，进一步修改(这不是脱裤子放屁？暂时没看出来有什么用)
    }
    static void reflectStepFour() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class clazz = new Person_test().getClass();
//        clazz.getDeclaredConstructor();
        //getDeclaredMethod和getMethod区别是获取方法的范围，后者只能获取公共方法
        Person_test person = (Person_test)clazz.newInstance();
        //感谢豆包ai支持我的参数不匹配的错误，我将无条件支持豆包ai OwO
        Method method  = clazz.getDeclaredMethod("sport",String.class,int.class);
        method.setAccessible(true);
        //这里的参数也要匹配上啊草草草草
        method.invoke(person,"runrunrun",12);
    }

    static void reflectStepFive() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class clazz = new Person_test().getClass();
        Constructor constructor = clazz.getConstructor(String.class,String.class);
        Object object = constructor.newInstance("fuziyu","123123");
        System.out.println(object);
    }

    static void reflectStepSix() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class clazz  = new Person_test().getClass();
        Class[] interfaceA = clazz.getInterfaces();
        Class superClass = clazz.getSuperclass();
        for(Class i:interfaceA){
            System.out.println(i.getName());
        }
        System.out.println(superClass.getName());
    }
    public static void main(String[] args)   {
        try{
            //1.获取class对象
            Java_25.reflectStepOne();
            //2.获取对象实例
            Java_25.reflectStepTwo();
            //3.操作对象实例某一个字段
            Java_25.reflectStepThree();
            //4.调用对象实例某个方法
            Java_25.reflectStepFour();
            //5.使用构造函数
            Java_25.reflectStepFive();
            //6.获取接口
            Java_25.reflectStepSix();
            //练习练习练练嘻嘻
            Java_25.reflectPractice();
        } catch (NoSuchFieldException|ClassNotFoundException|NoSuchMethodException| InvocationTargetException| InstantiationException| IllegalAccessException e) {
            throw new RuntimeException(e);
        }

    }

    static void reflectPractice() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        //跨包来说，没有别public修饰的方法或者函数不可以访问
        Class clazz =ReflectTest.class;
        Constructor constructor = clazz.getConstructor(String.class,String.class,boolean.class);
        //获取打印方法
        Method method = clazz.getDeclaredMethod("Print",String.class);
        Method method_set = clazz.getDeclaredMethod("setValue",String.class,String.class,boolean.class);
        method_set.setAccessible(true);
        //利用构造方法获取实例
        ReflectTest reflectClass = (ReflectTest)constructor.newInstance("231231","Reflect",true);
        Java_25.PrintParam(reflectClass,clazz,"funId","funName");
        Field field = clazz.getDeclaredField("funId");
        field.setAccessible(true);
        field.set(reflectClass,"123123");
        Java_25.PrintParam(reflectClass,clazz,"funId");
        method_set.invoke(reflectClass,"111111","fufufu",false);
        Java_25.PrintParam(reflectClass,clazz,"funId");
        Class superClass = clazz.getSuperclass();
        Method methodSuper = superClass.getDeclaredMethod("sayRun");
        Class[] interfaceList = clazz.getInterfaces();
        for (Class interfalceName:interfaceList){
            System.out.println(interfalceName);
        }
        //反射出来的父类函数子类不可以调用
//        methodSuper.invoke(reflectClass);
//        methodSuper.invoke(new methodSuper());
    }

    static void PrintParam(Object obj,Class A,String ...paramN) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        for(String paramName:paramN){
            Field field = A.getDeclaredField(paramName);
            field.setAccessible(true);
            Object value = field.get(obj);
            System.out.println(paramName+"获取属性值得到的数值"+value);
            Method method = A.getDeclaredMethod("Print",String.class);
            method.setAccessible(true);
            Object returnVaue = method.invoke(obj,"有参运行print方法");
            System.out.println(returnVaue);
        }
        System.out.println("---------------------->");
    }

}

//总结？
//反射就是用类来创建其class对象，通过class来反向获取这个类的属性，函数等，并且可以通过获取的属性对象，函数对象映射到这个类中，应该就是这样吧啊哈哈






